package com.juyou.rider.app.api.order;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.juyou.message.bo.RiderSpuBO;
import com.laituo.juyou.core.Const;
import com.laituo.juyou.core.exception.AdminServiceException;
import com.laituo.juyou.core.exception.ExceptionDefinition;
import com.laituo.juyou.core.exception.ServiceException;
import com.laituo.juyou.data.component.CacheComponent;
import com.laituo.juyou.data.domain.*;
import com.laituo.juyou.data.dto.CategoryTreeNodeDTO;
import com.laituo.juyou.data.dto.order.OrderRiderDTO;
import com.laituo.juyou.data.dto.rider.RiderLoginDTO;
import com.laituo.juyou.data.enums.OrderStatusType;
import com.laituo.juyou.data.enums.RiderOrderStatusType;
import com.laituo.juyou.data.mapper.OrderMapper;
import com.laituo.juyou.data.mapper.OrderSkuMapper;
import com.laituo.juyou.data.mapper.RiderOrderMapper;
import com.laituo.juyou.data.mapper.RiderSpuMapper;
import com.laituo.juyou.data.model.Page;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.rmi.ServerException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @description: 骑手订单接口
 * @author: fy
 * @date: 2020/03/03 21:02
 **/
@Service
public class RiderOderServiceImpl implements RiderOderService {

    @Autowired
    private CacheComponent cacheComponent;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private RiderOrderMapper riderOrderMapper;

    @Autowired
    private OrderSkuMapper orderSkuMapper;

    @Autowired
    private RiderSpuMapper riderSpuMapper;


    @Override
    public Page<OrderRiderDTO> getRiderOrderPage(Integer pageNo, Integer pageSize, String storageId) throws ServerException {
        Page<OrderRiderDTO> page = new Page<>();
        page.setCount(0);
        page.setPageNo(pageNo);
        page.setPageSize(pageSize);
        Map<String, String> orderAll = cacheComponent.getHashAll(Const.RIDER_ORDER + storageId);
        if (null != orderAll) {
            Collection<String> values = orderAll.values();
            List<OrderRiderDTO> collect = new ArrayList<>();
            if (values.size() > 0) {
                collect = values.stream().map(item -> JSONUtil.toBean(item, OrderRiderDTO.class))
                        .collect(Collectors.toList());
                int start = (pageNo - 1) * pageSize;
                int end = pageNo * pageSize;
                if (collect.size() < start) {
                    page.setCount(0);
                    page.setItems(null);
                } else if (collect.size() >= start && collect.size() <= end) {
                    page.setCount(collect.size() - start);
                    page.setItems(collect.subList(start, collect.size()));
                } else if (collect.size() > end) {
                    page.setCount(pageSize);
                    page.setItems(collect.subList(start, end));
                }
            }
        }
        return page;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized Boolean riderRobOrder(String riderId, String orderId, String storageId) throws ServerException, AdminServiceException {
        OrderDO orderDO = new OrderDO();
        orderDO.setOrderNo(orderId);
        String hashRaw = cacheComponent.getHashRaw(Const.RIDER_ORDER + storageId, orderId);
        if (StrUtil.isBlank(hashRaw)) {
            throw new AdminServiceException(ExceptionDefinition.RIDER_ORDER_MESSAGE_STATUS_ERROR_1);
        }
        OrderDO orderInfo = orderMapper.selectOne(orderDO);
        if (null == orderInfo || StrUtil.isBlank(orderInfo.getOrderNo())) {
            //订单不存在，删除订单信息
            cacheComponent.delHashObj(Const.RIDER_ORDER + storageId, orderId);
            //订单已配送
            if (orderInfo.getStatus() != OrderStatusType.WAIT_STOCK.getCode()) {
                cacheComponent.delHashObj(Const.RIDER_ORDER + storageId, orderId);
                throw new AdminServiceException(ExceptionDefinition.RIDER_ORDER_MESSAGE_STATUS_ERROR);
            }
            throw new AdminServiceException(ExceptionDefinition.RIDER_ORDER_MESSAGE_STATUS_ERROR);
        }
        RiderOrderDO riderOrderDO = new RiderOrderDO();
        BeanUtil.copyProperties(orderInfo, riderOrderDO);

        String payChannel = orderInfo.getPayChannel();
        riderOrderDO.setPayChannel(("WX".equals(payChannel) ? "微信" : "支付宝"));
        Date nowDate = new Date();
        riderOrderDO.setRiderId(Long.parseLong(riderId));
        riderOrderDO.setGmtCreate(nowDate);
        //送达时间
        riderOrderDO.setPredictTime(orderInfo.getGmtPredict());
        riderOrderDO.setGmtUpdate(nowDate);
        riderOrderDO.setStatus(RiderOrderStatusType.WAITING.getCode());
        riderOrderDO.setStoreName(orderInfo.getStorageName());
        riderOrderDO.setTotalPrice((orderInfo.getSkuTotalPrice().doubleValue() / 100));
        riderOrderDO.setGmtOrderCreate(orderInfo.getGmtCreate());
        if (riderOrderMapper.insert(riderOrderDO) > 0) {
            List<OrderSkuDO> orderSkuDOList = orderSkuMapper.selectList(new EntityWrapper<OrderSkuDO>().eq("order_no", orderId));
            if (orderSkuDOList.size() > 0) {
                List<RiderSpuDO> collect = orderSkuDOList.stream().map(item -> {
                    RiderSpuDO riderSpuDO = new RiderSpuDO();
                    riderSpuDO.setAmount(item.getNum().toString());
                    riderSpuDO.setSpuName(item.getTitle());
                    riderSpuDO.setUrl(item.getImg());
                    riderSpuDO.setUnitPrice(item.getPrice().doubleValue());
                    riderSpuDO.setRiderOrderId(riderOrderDO.getId());
                    return riderSpuDO;
                }).collect(Collectors.toList());
                riderSpuMapper.insertBatch(collect);
                //删除redis中的订单
                cacheComponent.delHashObj(Const.RIDER_ORDER + storageId, orderId);
            }
            return true;
        }
        throw new AdminServiceException(ExceptionDefinition.RIDER_ORDER_MESSAGE_SAVE_ERROR);
    }

    @Override
    public Page<RiderOrderDO> getRiderTaskPage(Integer pageNo, Integer pageSize, String riderId) throws ServerException {
        Wrapper<RiderOrderDO> wrapper = new EntityWrapper<RiderOrderDO>().eq("rider_id", riderId).between("status",
                RiderOrderStatusType.WAITING.getCode(), RiderOrderStatusType.ABNORMAL.getCode());
        List<RiderOrderDO> riderOrderDOS = riderOrderMapper.selectPage(new RowBounds((pageNo - 1) * pageSize, pageSize)
                , wrapper);
        return new Page<>(riderOrderDOS, pageNo, pageSize, riderOrderMapper.selectCount(wrapper));
    }

    /**
     * 查询历史订单
     *
     * @param pageNo   页码
     * @param pageSize 页码长度
     * @param riderId  骑手id
     * @return Page<RiderOrderDO>
     * @throws ServerException 异常
     */
    @Override
    public Page<RiderOrderDO> getHistoryTaskPage(Integer pageNo, Integer pageSize, String riderId, String startTime, String endTime) throws ServerException {
        Wrapper<RiderOrderDO> wrapper = new EntityWrapper<RiderOrderDO>().eq("rider_id", riderId).between("status",
                RiderOrderStatusType.TIMEOUT.getCode(), RiderOrderStatusType.COMPLETED.getCode());
        wrapper.between("gmt_update", startTime + " 00:00:00", endTime + " 23:59:59");
        List<RiderOrderDO> riderOrderDOS = riderOrderMapper.selectPage(new RowBounds((pageNo - 1) * pageSize, pageSize)
                , wrapper);
        return new Page<>(riderOrderDOS, pageNo, pageSize, riderOrderMapper.selectCount(wrapper));
    }

    @Override
    public RiderLoginDTO getRiderHistoryMoney(Long id, String startTime, String endTime) throws ServiceException {
        RiderLoginDTO riderLoginDTO = new RiderLoginDTO();
        Wrapper<RiderOrderDO> wrapper = new EntityWrapper<RiderOrderDO>().
                between("status", RiderOrderStatusType.TIMEOUT.getCode(),
                        RiderOrderStatusType.COMPLETED.getCode());
        wrapper.between("gmt_update", startTime + " 00:00:00", endTime + " 23:59:59");
        wrapper.eq("rider_id", id);
        List<RiderOrderDO> riderOrderList = riderOrderMapper.selectList(wrapper);
        riderLoginDTO.setNum(riderOrderList.size());
        if (riderOrderList.size() == 0) {
            riderLoginDTO.setIncome(new BigDecimal(0));
        } else {
            riderLoginDTO.setIncome(riderOrderList.stream()
                    .map(RiderOrderDO::getIncome).reduce(BigDecimal.ZERO, BigDecimal::add));
        }
        return riderLoginDTO;
    }
}
